{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 感知机Perceptron\n",
    "感知机是线性分类模型，输入实例的特征向量， 输出实例的类别， 取值+1或者-1. 感知机能对特征空间做超平面划分，以正负形式。\n",
    "\n",
    "## 步骤\n",
    "1. 导入基于误分类的损失函数\n",
    "2. 利用梯度下降法对损失函数进行极小化\n",
    "\n",
    "## 定义\n",
    "假设输入控件是 $ X \\subseteq R^n$ 输出为 y = {+1, -1}。 由输入控件到输出空间有如下函数：      \n",
    "$f(x) = sign(w \\bullet x + b)$    \n",
    "\n",
    "其中$w$ 和 $b$为感知机模型参数， $ X \\subseteq R^n$ 叫权值(weight)， $(w \\bullet x$ 叫内积。 sign是符号函数， 即：    \n",
    "\n",
    "$sign(x) = +1 (x>= 0) or = -1 (x < 0)$\n",
    "\n",
    "## 学习策略\n",
    "感知机学习的目标是求得一个能将训练集正实例点和负实例点完全正确分开的分离超平面。为了找到这个平面，就需要确定w，b， 即定义损失函数并将损失函数极小化。\n",
    "损失函数的一个自然选择是误分类点的总数，但这个选择不是w和b的连续可导函数， 所以损失函数的另一个选择是误分类点到超平面S的总距离。    \n",
    "首先输入空间 $R^n$ 中任一点 $x_0$ 到超平面S的距离为：   \n",
    "\n",
    "$\\frac{1}{\\Arrowvert{w}\\Arrowvert} \\Big\\arrowvert w \\bullet x_0 + b \\Big\\arrowvert$       \n",
    "\n",
    "经过各种代入换算之后， 得到感知机学习的损失函数, 给定训练集 $T = {(x_1, y_1)... (x_N, y_N)}$, 其中 $x_i \\in X = R_n, y_i \\in Y = {+1, -1}$, 感知机 $f(x) = sign(w \\bullet x + b)$ 定义的损失函数为：     \n",
    "\n",
    "$L(w, b) = - \\sum_{x_i \\in M} y_i(w \\bullet x_i + b)$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 好吧我根本没看懂感知机的计算过程 ：D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "import numpy as np\n",
    "#加载训练集数据路径\n",
    "class Perceptron:\n",
    "    def __init__(self, data, result):\n",
    "        #加载训练集数据\n",
    "        self.data = np.array(data)\n",
    "        self.result = np.array(result)\n",
    "        #初始化w和b\n",
    "        self.length = len(self.data[0])\n",
    "        self.w = np.zeros((1,self.length))\n",
    "        self.b = 0\n",
    "    def calculate(self):\n",
    "        i = 0\n",
    "        while i < len(self.data):\n",
    "            if self.result[i] * (np.dot(self.w, self.data[i]) + self.b) <= 0 :\n",
    "                self.w += self.result[i] * self.data[i]\n",
    "                self.b += self.result[i]\n",
    "                i = 0\n",
    "            else :\n",
    "                i += 1\n",
    "#             print(self.w)\n",
    "#             print(self.b)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[7. 2.]]\n",
      "-48\n"
     ]
    }
   ],
   "source": [
    "trainingData=[[1,2],[2,2],[3,1],[10,8],[6,9],[1,1],[3,6],[4,4],[6,8],[7,6],[3,2],[7,8],[6,2],[9,6],[11,3],[10,6],[12,5],[2,6]]\n",
    "resultData=[-1,-1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,1,1,1,1,-1]\n",
    "perceptron = Perceptron(trainingData, resultData)\n",
    "perceptron.calculate()\n",
    "print(perceptron.w)\n",
    "print(perceptron.b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
